package ace.module.oauth2.server.core.impl.manager.impl;

import ace.cmp.data.spring.data.jdbc.querydsl.rsql.core.manager.spring.AbstractSpringDtoManager;
import ace.cmp.spring.data.jdbc.querydsl.core.util.DeleteFlagUtils;
import ace.module.oauth2.server.api.model.dto.Oauth2AuthorizationDto;
import ace.module.oauth2.server.core.impl.dao.entity.Oauth2Authorization;
import ace.module.oauth2.server.core.impl.manager.Oauth2AuthorizationManager;
import ace.module.oauth2.server.core.impl.manager.cache.Oauth2AuthorizationCacheManager;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
* 客户端认证的令牌 spring data jdbc querydsl rsql manager implement.
*
* @author Caspar
*/
@Slf4j
@AllArgsConstructor
@Component
public class Oauth2AuthorizationManagerImpl
    extends AbstractSpringDtoManager<Oauth2Authorization, String, Oauth2AuthorizationDto>
    implements Oauth2AuthorizationManager {
  private final Oauth2AuthorizationCacheManager oAuth2AuthorizationCacheManager;

  @Override
  public String save(Oauth2Authorization authorization) {
    super.save(authorization, Boolean.TRUE);
    this.oAuth2AuthorizationCacheManager.clear(authorization);
    return authorization.getId();
  }

  @Override
  public boolean remove(String id) {
    Oauth2Authorization authorization = this.getRepository().getById(id);
    if (authorization == null) {
      return Boolean.TRUE;
    }
    super.remove(id);
    this.oAuth2AuthorizationCacheManager.clear(authorization);
    return Boolean.TRUE;
  }

  @Override
  public Oauth2Authorization getByRefreshTokenValue(String token) {
    Oauth2Authorization oauth2Authorization =
        this.oAuth2AuthorizationCacheManager.getByRefreshTokenValue(token);
    if (DeleteFlagUtils.isDelete(oauth2Authorization)) {
      return null;
    }
    return oauth2Authorization;
  }

  @Override
  public Oauth2Authorization getByAccessTokenValue(String token) {
    Oauth2Authorization oauth2Authorization =
        this.oAuth2AuthorizationCacheManager.getByAccessTokenValue(token);
    if (DeleteFlagUtils.isDelete(oauth2Authorization)) {
      return null;
    }
    return oauth2Authorization;
  }

  @Override
  public Oauth2Authorization getByAuthorizationCodeValue(String token) {
    Oauth2Authorization oauth2Authorization =
        this.oAuth2AuthorizationCacheManager.getByAuthorizationCodeValue(token);
    if (DeleteFlagUtils.isDelete(oauth2Authorization)) {
      return null;
    }
    return oauth2Authorization;
  }

  @Override
  public Oauth2Authorization getByState(String token) {
    Oauth2Authorization oauth2Authorization =
        this.oAuth2AuthorizationCacheManager.getByState(token);
    if (DeleteFlagUtils.isDelete(oauth2Authorization)) {
      return null;
    }
    return oauth2Authorization;
  }

  @Override
  public Oauth2Authorization getByToken(String token) {
    List<Supplier<Oauth2Authorization>> allTokenSuppliers =
        List.of(
            () -> this.oAuth2AuthorizationCacheManager.getByRefreshTokenValue(token),
            () -> this.oAuth2AuthorizationCacheManager.getByAccessTokenValue(token),
            () -> this.oAuth2AuthorizationCacheManager.getByAuthorizationCodeValue(token),
            () -> this.oAuth2AuthorizationCacheManager.getByState(token));
    return allTokenSuppliers.parallelStream()
        .map(Supplier::get)
        .filter(Objects::nonNull)
        .findFirst()
        .orElse(null);
  }

  @Override
  public Oauth2Authorization getFromCacheByIdAndDeleteFlagIsFalse(String id) {
    Oauth2Authorization authorization = this.oAuth2AuthorizationCacheManager.getById(id);
    if (DeleteFlagUtils.isDelete(authorization)) {
      return null;
    }
    return authorization;
  }

  @Override
  public Oauth2Authorization getFromCacheById(String id) {
    return this.oAuth2AuthorizationCacheManager.getById(id);
  }
}
